package com.yhy.wxzn.wms.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yhy.wxzn.common.enums.*;
import com.yhy.wxzn.common.exception.WmsBusinessException;
import com.yhy.wxzn.common.utils.ObjectFilterHelper;
import com.yhy.wxzn.wcs.device.rgv.enums.NodeType;
import com.yhy.wxzn.wcs.entity.WcsMapInfo;
import com.yhy.wxzn.wcs.service.IWcsMapInfoService;
import com.yhy.wxzn.wcs.service.IWmsAsyncMsgService;
import com.yhy.wxzn.wms.entity.*;
import com.yhy.wxzn.wms.mapper.WmsAsnDetailMapper;
import com.yhy.wxzn.wms.service.*;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @Description: 收货明细表
 * @Author: jeecg-boot
 * @Date:   2023-11-01
 * @Version: V1.0
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class WmsAsnDetailServiceImpl extends ServiceImpl<WmsAsnDetailMapper, WmsAsnDetail> implements IWmsAsnDetailService {

    @Autowired
    private WmsAsnDetailMapper asnDetailMapper;
    @Autowired
    private IWmsInventoryService inventoryService;
    @Autowired
    private IWcsMapInfoService mapInfoService;
    @Autowired
    private IWmsAsnService asnService;
    @Autowired
    private IWmsAsyncMsgService asyncMsgService;
    @Autowired
    private IWmsInboundConfigService inboundConfigService;

    @Override
    public IPage<WmsAsnDetail> pageSelf(Page<WmsAsnDetail> page, QueryWrapper<WmsAsnDetail> queryWrapper) {
        return asnDetailMapper.pageSelf(page,queryWrapper);
    }

    @Override
    public void addAsnDetail(WmsAsnDetail wmsAsnDetail) {
        ObjectFilterHelper.getObjDefault(wmsAsnDetail);
        this.save(wmsAsnDetail);
    }

    @Override
    public void detailReceive(WmsAsnDetail wmsAsnDetail) {
        WmsAsn asn = asnService.getById(wmsAsnDetail.getAsnId());
        //校验容器号
        List<WmsInventory> inventoryList = checkContainerNo(wmsAsnDetail);
        //生成或者更新库存
        saveOrUpdateInventory(inventoryList,wmsAsnDetail,asn);
        if(wmsAsnDetail.getInputReceiveQty().add(wmsAsnDetail.getReceivedQty()).compareTo(wmsAsnDetail.getDemonQty()) > 0){
            throw new WmsBusinessException("输入数量大于明细行需求数量,请核实!");
        }
        wmsAsnDetail.setReceivedQty(wmsAsnDetail.getReceivedQty().add(wmsAsnDetail.getInputReceiveQty()));
        this.saveOrUpdate(wmsAsnDetail);
        this.refreshAsnStatus(asn.getId());
    }

    public void refreshAsnStatus(String asnId) {
        WmsAsn asn = asnService.getById(asnId);
        //查找入库配置
        LambdaQueryWrapper<WmsInboundConfig> configQuery = new LambdaQueryWrapper<>();
        configQuery.eq(WmsInboundConfig::getStatus,ValidEnums.ENABLE.getValue());
        configQuery.eq(WmsInboundConfig::getOrderType,asn.getOrderType());
        WmsInboundConfig inboundConfig = inboundConfigService.getOne(configQuery);
        LambdaQueryWrapper<WmsAsnDetail> detailQuery = new LambdaQueryWrapper<>();
        detailQuery.eq(WmsAsnDetail::getAsnId,asnId);
        List<WmsAsnDetail> details = this.list(detailQuery);
        if(!CollectionUtils.isEmpty(details)){
            refreshOrderDetails(details,inboundConfig);
            refreshGroupAsn(asn,details,inboundConfig);
        }
    }

    /**
     * 更新入库单据的各种状态
     * @param asn
     * @param details
     * @param inboundConfig
     */
    private void refreshGroupAsn(WmsAsn asn, List<WmsAsnDetail> details,WmsInboundConfig inboundConfig) {
        //按收货状态分组
        Map<Integer,List<WmsAsnDetail>> receiveMap = details.stream().collect(Collectors.groupingBy(WmsAsnDetail::getDetailStatus));
        if(!CollectionUtils.isEmpty(receiveMap)){
            if(receiveMap.size() > 1){
                asn.setAsnStatus(WmsOrderStatusEnums.BFSH.getValue());
            }else{
                for (Integer detailStatus:receiveMap.keySet()){
                    if(detailStatus.intValue() == WmsOrderStatusEnums.XJ.getValue()){
                        asn.setAsnStatus(WmsOrderStatusEnums.XJ.getValue());
                    }else if(detailStatus.intValue() == WmsOrderStatusEnums.BFSH.getValue()){
                        asn.setAsnStatus(WmsOrderStatusEnums.BFSH.getValue());
                    }else if(detailStatus.intValue() == WmsOrderStatusEnums.YSH.getValue()){
                        asn.setAsnStatus(WmsOrderStatusEnums.SHWC.getValue());
                    }
                }
            }
        }
        //按分配状态分组
        Map<Integer,List<WmsAsnDetail>> allocateMap = details.stream().collect(Collectors.groupingBy(WmsAsnDetail::getAllocateStatus));
        if(!CollectionUtils.isEmpty(allocateMap)){
            if(allocateMap.size() > 1){
                asn.setAllocateStatus(WmsOrderStatusEnums.BFFP.getValue());
            }else{
                for (Integer allocateStatus:allocateMap.keySet()){
                    if(allocateStatus.intValue() == WmsOrderStatusEnums.XJ.getValue()){
                        asn.setAllocateStatus(WmsOrderStatusEnums.XJ.getValue());
                    }else if(allocateStatus.intValue() == WmsOrderStatusEnums.BFFP.getValue()){
                        asn.setAllocateStatus(WmsOrderStatusEnums.BFFP.getValue());
                    }else if(allocateStatus.intValue() == WmsOrderStatusEnums.YFP.getValue()){
                        asn.setAllocateStatus(WmsOrderStatusEnums.FPWC.getValue());
                    }
                }
            }
        }
        //按上架状态分组
        Map<Integer,List<WmsAsnDetail>> putAwayMap = details.stream().collect(Collectors.groupingBy(WmsAsnDetail::getPutAwayStatus));
        if(!CollectionUtils.isEmpty(putAwayMap)){
            if(putAwayMap.size() > 1){
                asn.setPutAwayStatus(WmsOrderStatusEnums.BFSJ.getValue());
            }else{
                for (Integer putAwayStatus:putAwayMap.keySet()){
                    if(putAwayStatus.intValue() == WmsOrderStatusEnums.XJ.getValue()){
                        asn.setPutAwayStatus(WmsOrderStatusEnums.XJ.getValue());
                    }else if(putAwayStatus.intValue() == WmsOrderStatusEnums.BFSJ.getValue()){
                        asn.setPutAwayStatus(WmsOrderStatusEnums.BFSJ.getValue());
                    }else if(putAwayStatus.intValue() == WmsOrderStatusEnums.YSJ.getValue()){
                        asn.setPutAwayStatus(WmsOrderStatusEnums.SJWC.getValue());
                    }
                }
            }
        }
        //按过账状态分组
        if(!ObjectUtils.isEmpty(inboundConfig) && (inboundConfig.getReceiveSycErp() || inboundConfig.getPutSynErp())){
            Map<Integer,List<WmsAsnDetail>> synStatusMap = details.stream().collect(Collectors.groupingBy(WmsAsnDetail::getSyncStatus));
            if(!CollectionUtils.isEmpty(synStatusMap)){
                if(synStatusMap.size() > 1){
                    asn.setSyncStatus(WmsSyncStatusEnums.BFGZ.getValue());
                }else{
                    for (Integer syncStatus:synStatusMap.keySet()){
                        if(syncStatus.intValue() == WmsSyncStatusEnums.WGZ.getValue()){
                            asn.setSyncStatus(WmsSyncStatusEnums.WGZ.getValue());
                        }else if(syncStatus.intValue() == WmsSyncStatusEnums.GZZ.getValue()){
                            asn.setSyncStatus(WmsSyncStatusEnums.BFGZ.getValue());
                        }else if(syncStatus.intValue() == WmsSyncStatusEnums.GZCG.getValue()
                        || syncStatus.intValue() == WmsSyncStatusEnums.GZSB.getValue()){
                            asn.setSyncStatus(WmsSyncStatusEnums.GZWC.getValue());
                        }
                    }
                }
            }
        }else{
            asn.setSyncStatus(WmsSyncStatusEnums.WXGZ.getValue());
        }
        asnService.saveOrUpdate(asn);
    }

    /**
     * 更新入库单据Detail的各种状态
     * @param details
     * @param inboundConfig
     */
    private void refreshOrderDetails(List<WmsAsnDetail> details,WmsInboundConfig inboundConfig) {
        for (WmsAsnDetail detail: details) {
            //需求数量
            BigDecimal demonQty = detail.getDemonQty();
            //已收货数量
            BigDecimal receivedQty = detail.getReceivedQty();
            //已分配数量
            BigDecimal allocateQty = detail.getAllocateQty();
            //已上架数量
            BigDecimal putAwayQty = detail.getMovedQty();
            //过账数量
            BigDecimal syncQty = detail.getSyncQty();
            if(receivedQty.compareTo(BigDecimal.ZERO) == 0){
                detail.setDetailStatus(WmsOrderStatusEnums.XJ.getValue());
            }else if(receivedQty.compareTo(demonQty) == 0){
                detail.setDetailStatus(WmsOrderStatusEnums.YSH.getValue());
            }else{
                detail.setDetailStatus(WmsOrderStatusEnums.BFSH.getValue());
            }
            if(allocateQty.compareTo(BigDecimal.ZERO) == 0){
                detail.setAllocateStatus(WmsOrderStatusEnums.XJ.getValue());
            }else if(allocateQty.compareTo(demonQty) == 0){
                detail.setAllocateStatus(WmsOrderStatusEnums.YFP.getValue());
            }else{
                detail.setAllocateStatus(WmsOrderStatusEnums.BFFP.getValue());
            }
            if(putAwayQty.compareTo(BigDecimal.ZERO) == 0){
                detail.setPutAwayStatus(WmsOrderStatusEnums.XJ.getValue());
            }else if(putAwayQty.compareTo(demonQty) == 0){
                detail.setPutAwayStatus(WmsOrderStatusEnums.YSJ.getValue());
            }else{
                detail.setPutAwayStatus(WmsOrderStatusEnums.BFSJ.getValue());
            }
            if(!ObjectUtils.isEmpty(inboundConfig)
                && (inboundConfig.getReceiveSycErp() || inboundConfig.getPutSynErp())
            ){
                if(syncQty.compareTo(BigDecimal.ZERO) == 0){
                    detail.setSyncStatus(WmsSyncStatusEnums.WGZ.getValue());
                }else if(syncQty.compareTo(demonQty) == 0){
                    detail.setSyncStatus(WmsSyncStatusEnums.GZCG.getValue());
                }else{
                    detail.setSyncStatus(WmsSyncStatusEnums.GZZ.getValue());
                }
            }else{
                detail.setSyncStatus(WmsSyncStatusEnums.WXGZ.getValue());
            }
        }
        this.saveOrUpdateBatch(details);
    }

    private void saveOrUpdateInventory(List<WmsInventory> inventoryList,WmsAsnDetail wmsAsnDetail,WmsAsn asn) {
        WmsInventory inventory;
        if(CollectionUtils.isEmpty(inventoryList)){
            inventory = new WmsInventory();
            inventory.setItemId(wmsAsnDetail.getItemId());
            BeanUtils.copyProperties(wmsAsnDetail,inventory);
            inventory.setId(null);
            inventory.setLocationId(asn.getReceiveLocationId());
            inventory.setInvQty(wmsAsnDetail.getInputReceiveQty());
            inventory.setPalletNo(wmsAsnDetail.getPalletNo());
            inventory.setBoxNo(wmsAsnDetail.getBoxNo());
            inventoryService.save(inventory);
        }else{
            inventory = inventoryList.get(0);
            inventory.setInvQty(inventory.getInvQty().add(wmsAsnDetail.getInputReceiveQty()));
            inventoryService.saveOrUpdate(inventory);
        }
    }

    private List<WmsInventory> checkContainerNo(WmsAsnDetail wmsAsnDetail) {
        LambdaQueryWrapper<WmsInventory> invQuery = new LambdaQueryWrapper<>();
        LambdaQueryWrapper<WcsMapInfo> locQuery = new LambdaQueryWrapper<>();
        invQuery.eq(WmsInventory::getItemId,wmsAsnDetail.getItemId());
        if(!StringUtils.isEmpty(wmsAsnDetail.getPalletNo())){
            invQuery.eq(WmsInventory::getPalletNo,wmsAsnDetail.getPalletNo());
        }
        if(!StringUtils.isEmpty(wmsAsnDetail.getBoxNo())){
            invQuery.eq(WmsInventory::getBoxNo,wmsAsnDetail.getBoxNo());
        }
        if(!StringUtils.isEmpty(wmsAsnDetail.getLot01())){
            invQuery.eq(WmsInventory::getLot01,wmsAsnDetail.getLot01());
        }
        if(!StringUtils.isEmpty(wmsAsnDetail.getLot02())){
            invQuery.eq(WmsInventory::getLot02,wmsAsnDetail.getLot02());
        }
        if(!StringUtils.isEmpty(wmsAsnDetail.getLot03())){
            invQuery.eq(WmsInventory::getLot03,wmsAsnDetail.getLot03());
        }
        if(!StringUtils.isEmpty(wmsAsnDetail.getLot04())){
            invQuery.eq(WmsInventory::getLot04,wmsAsnDetail.getLot04());
        }
        if(!StringUtils.isEmpty(wmsAsnDetail.getLot05())){
            invQuery.eq(WmsInventory::getLot05,wmsAsnDetail.getLot05());
        }
        if(!StringUtils.isEmpty(wmsAsnDetail.getLot06())){
            invQuery.eq(WmsInventory::getLot06,wmsAsnDetail.getLot06());
        }
        if(!StringUtils.isEmpty(wmsAsnDetail.getLot07())){
            invQuery.eq(WmsInventory::getLot07,wmsAsnDetail.getLot07());
        }
        List<WmsInventory> inventoryList = inventoryService.list(invQuery);
        if(!CollectionUtils.isEmpty(inventoryList)){
            List<String> locIds = inventoryList.stream().map(WmsInventory::getLocationId).collect(Collectors.toList());
            locQuery.eq(WcsMapInfo::getNodeType, NodeType.P.getCodeNum());
            locQuery.in(WcsMapInfo::getId,locIds);
            List<WcsMapInfo> coords = mapInfoService.list(locQuery);
            if(!CollectionUtils.isEmpty(coords)){
                throw new WmsBusinessException("该箱号已在存货库位,请核实!");
            }else{
                return inventoryList;
            }
        }
        return inventoryList;
    }
}
